local PlayScene = class("PlayScene", function()
    return display.newScene("PlayScene");
end);

local FruitItem = import("app.widgets.fruitItem");
local schedule = require("framework.scheduler");

function PlayScene:ctor()
	print("PlayScene:ctor()");
	self.m_curLevel = 1;

	self:initUI();
end 

function PlayScene:onEnter()
	print("PlayScene:onEnter()");
    self:startGame();
end

function PlayScene:onExit()
	print("PlayScene:onExit()");

	if self.m_schedule_handler then 
		schedule.unscheduleGlobal(self.m_schedule_handler);
		self.m_schedule_handler = nil;
	end
end

function PlayScene:onReturn()
	app:enterScene("MainScene", "FADE");
end

function PlayScene:initData()
	self.m_highScore = 0;
	self.m_curScore = 0;

	self:initLevelData(self.m_curLevel);
	self:updateScore(self.m_curScore,self.m_highScore);	
end

function PlayScene:onReplay()
	print("onReplay()");
	self:startGame();
end

function PlayScene:onPlayNext()
	print("onPlayNext()");
	self.m_curLevel = self.m_curLevel + 1;
	self:startGame();
end

function PlayScene:startGame()
	self:initData();
	self:removeAllFruit();
	self:initFruitMatrix();

	schedule.performWithDelayGlobal(handler(self,self.playStartAnim), 1.5);
end 

function PlayScene:playStartAnim()
	if not self.m_startLayer then
		local StartLayer = import("app.widgets.startLayer");
		self.m_startLayer = StartLayer.new();
		self.m_startLayer:addTo(self);
		self.m_startLayer:setDelegate(self);
	end 
	self.m_startLayer:show();
end 

function PlayScene:onStartPlay()
	self:startGameTimer();
end

function PlayScene:updateLevel(level)
	self.m_hightScoreLabel:setString(string.format("level :%s",level));
end

function PlayScene:updateTime(time)
	time = tonumber(time);
	time = time and string.format("time:%s",time) or "time";
	self.m_timeLabel:setString(time);
end

function PlayScene:updateScore(score)
	self.m_scoreLabel:setString(string.format("score:%s",score));	
end 

function PlayScene:initLevelData(level)
	local levels = import("app.config.levels");
	level = tonumber(level) or -1;

	local config;
	if levels[level] then 
		config = levels[level];
	else
		config = import("app.config.levelBaseConfig");
	end

	self.m_rowCount = config.rowCount;
	self.m_colCount = config.colCount;
	self.m_target = config.target;
	self.m_fruitTypeCount = config.fruitTypeCount;
	self.m_totalTime = config.totalTime;
	self.m_stepCount = config.stepCount;
	self.m_targetExt = config.targetExt;

	print("target = "..self.m_target);

	self:updateTime(self.m_totalTime);
	self:updateLevel(self.m_curLevel);
end

function PlayScene:startGameTimer()
	print("startGameTimer");
	if self.m_totalTime > 0 then 
		self:updateTime(self.m_totalTime);
		self.m_schedule_handler = schedule.scheduleGlobal(handler(self,self.onGameTimerEvent),1);
	end
end

function PlayScene:onGameTimerEvent()
	self.m_totalTime = self.m_totalTime - 1;
	self:updateTime(self.m_totalTime);
	if self.m_totalTime == 0 then
		self:onGameOver();
		schedule.unscheduleGlobal(self.m_schedule_handler);
		self.m_schedule_handler = nil;
	end 
end

function PlayScene:onGameOver()
	print("play game over");
	self:inactive();
	
	if not self.m_gameOver then 
		local GameOver = import("app.widgets.gameover");
		self.m_gameOver = GameOver.new();
		self.m_gameOver:setDelegate(self);
		self.m_gameOver:addTo(self);
	end
	self.m_gameOver:show(self.m_curScore >= self.m_target);
end

function PlayScene:initUI()
	display.newSprite("background.png")
		:pos(display.cx,display.cy)
		:addTo(self)

	cc.ui.UIPushButton.new("buttons_quit.png",{scale9 = false})
		:onButtonClicked(handler(self,self.onReturn))
		:align(display.TOP_LEFT,display.left+20, display.top-20)
		:addTo(self)	

	local function _getTextParam(textString)
		local textParam = {
			UILabelType = 2, 
			text = textString, 
			size = 30,
			align = cc.ui.TEXT_ALIGN_CENTER,
	        color = cc.c3b(255,255,0),
	        dimensions = cc.size(200,40),
		};
		return textParam;
	end

	self.m_hightScoreLabel = cc.ui.UILabel.new(_getTextParam("high score"));
    self.m_hightScoreLabel:pos(display.cx-100, display.top-40);
    self.m_hightScoreLabel:addTo(self);


    self.m_scoreLabel = cc.ui.UILabel.new(_getTextParam("score"));
    self.m_scoreLabel:align(display.TOP_RIGHT,display.right+20, display.top-20);
    self.m_scoreLabel:addTo(self);

    self.m_timeLabel = cc.ui.UILabel.new(_getTextParam("time"));
    self.m_timeLabel:pos(display.cx-100, display.top - 80);
    self.m_timeLabel:addTo(self);

    self.m_martixLayer = display.newSprite("bg_blank.png")
		:pos(display.cx,display.cy)
		:setContentSize(cc.size(display.width,display.height))
		:addTo(self);
end

function PlayScene:initFruitMatrix()
	--print("playscene......initFruitMatrix......")
	self.m_fruitMatrix = {};
	self.m_activeFruits = {};

	for row = 1,self.m_rowCount do 
		for col = 1,self.m_colCount do 
			if row == 1 and col == 2 then 
				self:createFruitItem(self.m_fruitMatrix[1].m_type,row,col);
			else 
				self:createFruitItem(nil,row,col);
			end 
		end 
	end 
end

function PlayScene:createFruitItem(index,row,col,time)	
	--print("playscene......createFruitItem......"..row.."..."..col)
	local item = FruitItem.new(index,row,col,self.m_fruitTypeCount);
	local map = self:getFruitMap();
	local pos = map:getItemPos(row,col);
	item:setPosition(pos);
	self.m_fruitMatrix[(row-1)*self.m_colCount + col] = item;

	item:drop(display.height*1.1,time,display.height*1.1);
	self.m_martixLayer:addChild(item);
	item:setTouchEnabled(true);

	item:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
		if event.name == "ended" then 
            if item.m_isActive then            	
            	if #self.m_activeFruits >= 2 then
            		--print("TODO:clear this item!!!");
            		self:removeActive();
            		self:dropFruit();
            		
            	else
            		self:inactive();
            	end 
            else
            	self:inactive();
            	self:activeNeighbor(item);
            end
	    end 

	    if event.name == "began" then 
	    	return true;
	    end 
	end);
end

function PlayScene:checkHasSameFruit()
	local hasSameItem = self:_checkHasSameInMap();
	if not hasSameItem then 
		print("has not same item....");
		self:removeAllFruit();
		self:initFruitMatrix();
	end
end

function PlayScene:removeAllFruit()
	if not self.m_fruitMatrix then
		return;
	end

	for row = 1,self.m_rowCount do 
		for col = 1,self.m_colCount do 
			local item = self.m_fruitMatrix[(row - 1)*self.m_colCount + col];
			if item then 
				item:removeSelf();
			end 
		end 
	end 
	self.m_fruitMatrix = {};
	self.m_activeFruits = {};
end

function PlayScene:inactive()
	for _,item in pairs(self.m_activeFruits) do 
		if item then 
			item:stopAllActions();
			item:setActive(false);
		end
	end 
	self.m_activeFruits = {};
end

function PlayScene:selecteFruitItem(item)
	if item then 
		item:setActive(true);
		table.insert(self.m_activeFruits,item);
	end 
end 

function PlayScene:activeNeighbor(item)	
	local checkItems = {};

	local function _selecteSameNeighborItem(item)
		if not item.m_isActive then   
			self:selecteFruitItem(item)
			checkItems = self:searchSameNeighbor(item,checkItems);
		end
		if #checkItems > 0 then
			local item = table.remove(checkItems);
			_selecteSameNeighborItem(item);
		end
	end 
	_selecteSameNeighborItem(item);

	if #self.m_activeFruits == 1 then 
		self:inactive();
	end 
end

function PlayScene:searchSameNeighbor(item,sameArray)
	local index = item.m_type;
	local row = item.m_row;
	local col = item.m_col;
	
	--print("searchSameNeighbor ----> isLeftSame.....");
	local isSame,item = self:isLeftSame(index, row, col);
	if isSame then 
		table.insert(sameArray,item);
	end 

	--print("searchSameNeighbor ----> isRightSame.....");
	local isSame,item = self:isRightSame(index, row, col);
	if isSame then 
		table.insert(sameArray,item);
	end 

	--print("searchSameNeighbor ----> isTopSame.....");
	local isSame,item = self:isTopSame(index, row, col);
	if isSame then 
		table.insert(sameArray,item);
	end 
	
	--print("searchSameNeighbor ----> isBottomSame.....");	
	local isSame,item = self:isBottomSame(index, row, col);
	if isSame then 
		table.insert(sameArray,item);
	end 

	return sameArray;
end

function PlayScene:_checkIsSameFruit(index,newRow,newCol)
	--print("newRow = "..newRow.." newCol = "..newCol);
	local temp = (newRow - 1)*self.m_colCount + newCol;
	local checkItem = self.m_fruitMatrix[temp];
	if checkItem then 
		local checkIndex = checkItem.m_type;
		--print("checkIndex = "..checkIndex);
		if checkIndex == index then 
			return true,checkItem;
		end 
	end
	return false;
end

-- 同行左边
function PlayScene:isLeftSame(index,row,col)
	if col > 1 then 
		local newCol = col - 1;
		local newRow = row;
		--print("search left ......");
		return self:_checkIsSameFruit(index,newRow,newCol);
	end 
	return false;
end
-- 同行右边
function PlayScene:isRightSame(index,row,col)
	if col < self.m_colCount then 
		local newCol = col + 1;
		local newRow = row;
		--print("search right ......");
		return self:_checkIsSameFruit(index,newRow,newCol);
	end
	return false;
end

--同列下边
function PlayScene:isBottomSame(index,row,col)
	if row > 1 then 
		local newCol = col;
		local newRow = row - 1;
		--print("search bottom ......");
		return self:_checkIsSameFruit(index,newRow,newCol);
	end
	return false;
end

--同列上边
function PlayScene:isTopSame(index,row,col)
	if row < self.m_rowCount then 
		local newCol = col;
		local newRow = row + 1;
		--print("search top ......");
		return self:_checkIsSameFruit(index,newRow,newCol);
	end
	return false;
end

function PlayScene:removeActive()
	for _,item in pairs(self.m_activeFruits) do 
		if item then 
			self.m_fruitMatrix[(item.m_row - 1)*self.m_colCount + item.m_col] = nil;
			-- item:removeFromParent();

			-- local circleSprite = display.newSprite("circle.png");
			-- circleSprite:pos(item:getPosition());
			-- circleSprite:addTo(self);
			-- circleSprite:setScale(0);

			-- local seq = cc.Sequence:create(cc.ScaleTo:create(0.3,0.8),cc.CallFunc:create(function() circleSprite:removeSelf() end));
			-- circleSprite:runAction(seq);

			local emitter = cc.ParticleSystemQuad:create("stars.plist");
			emitter:setPosition(item:getPosition());
			local batch = cc.ParticleBatchNode:createWithTexture(emitter:getTexture());
			batch:addChild(emitter);
			self.m_martixLayer:addChild(batch);

			item:removeSelf();
		end 
	end 

	local count = #self.m_activeFruits;
	local score = count <= 2 and 5 or 3^(count -2) + 5;
	self.m_highScore = math.max(self.m_highScore,score);
	self.m_curScore = self.m_curScore + score;
	self:updateScore(self.m_curScore);
	
	self.m_activeFruits = {};
end

function PlayScene:dropFruit()
	local removeArry = {};

	for col = 1,self.m_colCount do 
		local removeCount = 0;
		for row = 1,self.m_rowCount do 
			local item = self.m_fruitMatrix[(row - 1)*self.m_colCount+col];
			if item == nil then
				removeCount = removeCount + 1;
			else 
				if removeCount > 0 then
					local newRow = row - removeCount;
					item.m_row = newRow;
					self.m_fruitMatrix[(newRow - 1)*self.m_colCount + col] = item;
					self.m_fruitMatrix[(row - 1)*self.m_colCount + col] = nil;

					local _,itemHeight = FruitItem.getSize();
					local diff = itemHeight*removeCount;

					local sx,sy = item:getPosition();
					local newPos = cc.p(sx,sy-diff);
					item:setPosition(newPos);
					item:drop(diff,0.3);
				end 
			end 
		end

		removeArry[col] = removeCount;
	end 

	for col = 1,self.m_colCount do 
		if removeArry[col] > 0 then
			for row = self.m_rowCount - removeArry[col] + 1,self.m_rowCount do 
				--print("add new item .. row = "..row.." col = "..col);
				self:createFruitItem(nil, row, col,0.3);
			end 
		end 
	end

	local delay = cc.DelayTime:create(0.3);
	local sequence = cc.Sequence:create(delay, cc.CallFunc:create(self.checkHasSameFruit));
    self:runAction(sequence)
	-- self:checkHasSameFruit();
end

function PlayScene:_checkHasSameInMap()
	print("_checkHasSameInMap........");

	--从下往上，寻找上面有没有相同的
	for row = 1,self.m_rowCount do 
		for col = 1,self.m_colCount do 
			local item = self.m_fruitMatrix[(row - 1)*self.m_colCount + col];
			if item then 
				local index = item.m_type;
				local row = item.m_row;
				local col = item.m_col;

				--print("_checkHasSameInMap ----> isTopSame.....");
				local isSame,item = self:isTopSame(index, row, col);
				if isSame then 
					print("top is same  row = "..row.." col = "..col.." index = "..index);
					return true;
				end 
			end
		end 
	end 

	-- 从左往右，寻找右边的有没相同的
	for col = 1,self.m_colCount do 
		for row = 1,self.m_rowCount do 
			local item = self.m_fruitMatrix[(row - 1)*self.m_colCount + col];
			if item then 
				local index = item.m_type;
				local row = item.m_row;
				local col = item.m_col;

				--print("_checkHasSameInMap ----> isRightSame.....");
				local isSame,item = self:isRightSame(index, row, col);
				if isSame then 
					print("right is same  row = "..row.." col = "..col.." index = "..index);
					return true;
				end 
			end 
		end 
	end 

	return false;
end

function PlayScene:getFruitMap()
	local itemWidth,itemHeight = FruitItem.getSize();
	local FruitMap = import("app.widgets.fruitMap");
	local fruitMap = FruitMap.new(self.m_rowCount,self.m_colCount,0,itemWidth,itemHeight);

	return fruitMap;
end

return PlayScene
